﻿using System;
using System.Architecture;
using System.Collections.Generic;
using System.Composition;
using System.Data.Services.Client;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using DataVirtualization;
using HDK.Demo.svcNetflix;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace HDK.Demo.Pages.Views
{
    [Shared]
    [ExportView("Pages/DataVirtualizationTest", "DataVirtualizationTest", new string[] { "MainRegion" })]
    public sealed partial class DataVirtualizationTest : UserControl, IPageView
    {
        public DataVirtualizationTest()
        {
            this.InitializeComponent();
        }

        public string Title
        {
            get { return "Data Virtualization"; }
        }
    }

    /// <summary>
    /// Demo customer object.
    /// </summary>
    public class Customer
    {
        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        /// <value>The id.</value>
        public int Id { get; set; }

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name { get; set; }

        /// <summary>
        /// Some dummy data to give the instance a bigger memory footprint.
        /// </summary>
        private byte[] data = new byte[100];
    }

    /// <summary>
    /// Demo implementation of IItemsProvider returning dummy customer items after
    /// a pause to simulate network/disk latency.
    /// </summary>
    public class DemoCustomerProvider : IItemsProvider<Customer>
    {
        private int _count;
        private readonly int _fetchDelay;

        /// <summary>
        /// Initializes a new instance of the <see cref="DemoCustomerProvider"/> class.
        /// </summary>
        /// <param name="count">The count.</param>
        /// <param name="fetchDelay">The fetch delay.</param>
        public DemoCustomerProvider(int count, int fetchDelay)
        {
            _count = count;
            _fetchDelay = fetchDelay;
        }

        /// <summary>
        /// Fetches the total number of items available.
        /// </summary>
        /// <returns></returns>
        public Task<int> FetchCount()
        {
            Debug.WriteLine("FetchCount");
            //Thread.Sleep(_fetchDelay);
            return Task.Delay(_fetchDelay).ContinueWith<int>(t => _count);
        }

        /// <summary>
        /// Fetches a range of items.
        /// </summary>
        /// <param name="startIndex">The start index.</param>
        /// <param name="count">The number of items to fetch.</param>
        /// <returns></returns>
        public Task<IList<Customer>> FetchRange(int startIndex, int pageCount)//, out int overallCount)
        {
            Debug.WriteLine("FetchRange: " + startIndex + "," + pageCount);
            //Thread.Sleep(_fetchDelay);
            //overallCount = _count;
            return Task.Delay(_fetchDelay).ContinueWith<IList<Customer>>(t =>
                {
                    List<Customer> list = new List<Customer>();
                    for (int i = startIndex; i < startIndex + pageCount && i < this._count; i++)
                    {
                        Customer customer = new Customer { Id = i + 1, Name = "Customer " + (i + 1) };
                        list.Add(customer);
                    }
                    return list;
                });
        }

        /// <summary>
        /// Pretend to insert an item.
        /// </summary>
        public void InsertItem()
        {
            _count++;
        }

        /// <summary>
        /// Pretend to remove an item.
        /// </summary>
        public void RemoveItem()
        {
            _count--;
        }
    }









    /// <summary>
    /// Demo implementation of IItemsProvider returning dummy customer items after
    /// a pause to simulate network/disk latency.
    /// </summary>
    public class NetflixTitleProvider : IItemsProvider<Title>
    {
        private int _count = -1;
        NetflixCatalog NetFlix = null; 
        /// <summary>
        /// Initializes a new instance of the <see cref="DemoCustomerProvider"/> class.
        /// </summary>
        /// <param name="count">The count.</param>
        /// <param name="fetchDelay">The fetch delay.</param>
        public NetflixTitleProvider()
        {
            NetFlix = new svcNetflix.NetflixCatalog(new Uri("http://odata.netflix.com/Catalog"));
            NetFlix.UseDefaultCredentials = true;
            //NetFlix.SendingRequest+=(s,e)=>
            //    {
                    

            //    });
//            NetFlix.UsePostTunneling = true;


        }

        /// <summary>
        /// Fetches the total number of items available.
        /// </summary>
        /// <returns></returns>
        public async Task<int> FetchCount()
        {
            Debug.WriteLine("FetchCount");

            if (_count == -1)
            {
                try
                {

                    IEnumerable<Title> titles = await ((DataServiceQuery<Title>)NetFlix.Titles).ExecuteAsync();
                    _count = titles.Count();
                }
                catch (Exception exc)
                {

                }
            }
            return _count;
        }

        /// <summary>
        /// Fetches a range of items.
        /// </summary>
        /// <param name="startIndex">The start index.</param>
        /// <param name="count">The number of items to fetch.</param>
        /// <returns></returns>
        public async Task<IList<Title>> FetchRange(int startIndex, int pageCount)//, out int overallCount)
        {
            Debug.WriteLine("FetchRange: " + startIndex + "," + pageCount);



            IEnumerable<Title> titles = await ((DataServiceQuery<Title>)NetFlix.Titles
                            .Expand("Genres,AudioFormats,AudioFormats/Language,Awards,Cast")
                            .Where(t => t.Rating == "PG")
                            .OrderByDescending(t => t.ReleaseYear)
                            .Skip(startIndex)
                            .Take(pageCount)).ExecuteAsync();

            return titles.ToList();
            
            //return Task.Delay(_fetchDelay).ContinueWith<IList<Customer>>(t =>
            //{
            //    List<Customer> list = new List<Customer>();
            //    for (int i = startIndex; i < startIndex + pageCount && i < this._count; i++)
            //    {
            //        Customer customer = new Customer { Id = i + 1, Name = "Customer " + (i + 1) };
            //        list.Add(customer);
            //    }
            //    return list;
            //});
        }

        /// <summary>
        /// Pretend to insert an item.
        /// </summary>
        public void InsertItem()
        {
            //_count++;
        }

        /// <summary>
        /// Pretend to remove an item.
        /// </summary>
        public void RemoveItem()
        {
            //_count--;
        }
    }

    [Shared]
    [ExportViewModel("DataVirtualizationTest")]
    public class DataVirtualizationTestViewModel : NavigationAwareViewModel
    {
        private AsyncVirtualizingCollection<Title> customerList;
        public AsyncVirtualizingCollection<Title> CustomerList
        { 
            get {
                return customerList; 
            } 
            set 
            {
                SetProperty<AsyncVirtualizingCollection<Title>>(ref customerList, value); 
            } 
        }

        public DataVirtualizationTestViewModel()
        {
            //DemoCustomerProvider CustomerProvider = new DemoCustomerProvider(1000 /*number of items*/, 2000 /*delay*/);
            //CustomerList = new AsyncVirtualizingCollection<Customer>(CustomerProvider, 5 /*page size*/, 3000 /*timeout*/);
            
            NetflixTitleProvider netflixTitleProvider = new NetflixTitleProvider();
            CustomerList = new AsyncVirtualizingCollection<Title>(netflixTitleProvider, 15 /*page size*/, 3000 /*timeout*/);
        }


    }



}
